﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using Evolution.Security;

namespace Evolution.UI.WebParts
{
    [Serializable]
    public class CurrentUserAssertion : BaseAssertion
    {
        #region Properties

        public override string Caption
        {
            get { return "Current user"; }
        }

        public SecurityEntity SecurityEntity
        {
            get;
            set;
        }

        public CurrentUserOperator Operator { get; set; }

        #endregion

        #region Methods

        public override void CreateInterface(ControlCollectionBuilder builder, PageActionEditor editor, int index)
        {
            DropDownList list = new DropDownList();
            list.ID = "CUOperator" + index;
            list.Width = Unit.Pixel(150);
            list.Items.Add(new ListItem("belongs to", CurrentUserOperator.BelongsTo.ToString()));
            list.Items.Add(new ListItem("does not belong to", CurrentUserOperator.DoesNotBelongTo.ToString()));
            list.Items.Add(new ListItem("is site administrator", CurrentUserOperator.IsSiteAdministrator.ToString()));
            list.Items.Add(new ListItem("is not site administrator", CurrentUserOperator.IsNotSiteAdministrator.ToString()));

            builder.AddControl(list);

            builder.AddStaticText(String.Format("<div id=\"PeopleEditorContainer{0}\"><br/>", index));

            PeopleEditor pe = new PeopleEditor();
            pe.ID = "CUPeopleEditor" + index;
            pe.AllowEmpty = true;
            pe.AllowTypeIn = true;
            pe.MultiSelect = true;
            pe.PlaceButtonsUnderEntityEditor = false;
            pe.SelectionSet = "User,DL,SecGroup,SPGroup";
            pe.Width = Unit.Pixel(200);
            pe.Rows = 2;
            pe.ValidatorEnabled = true;
            
            builder.AddControl(pe);

            builder.AddErrorPlaceholder("CUValue" + index);

            builder.AddStaticText("</div>");

            editor.AddClientArray("CurrentUser_OperatorIDs", "'" + list.ClientID + "'");
            editor.AddClientArray("CurrentUser_OperatorIDs", "'PeopleEditorContainer" + index + "'");

            list.Attributes["onchange"] = String.Format("Evolution_Pawp_SetCurrentUserOperator(this.selectedIndex, document.getElementById('PeopleEditorContainer{0}'))", index);
        }

        public override bool IsValidAssertion(PageActionWebPart part, out string errorMessage)
        {
            errorMessage = String.Empty;

            if (this.SecurityEntity == null)
                errorMessage = "No SecurityEntity specified.";
            else if ((int)this.Operator < 2 && this.SecurityEntity.IsEmpty)
                errorMessage = "No user accounts, group accounts in Active Directory or SharePoint group names specified.";

            return String.IsNullOrEmpty(errorMessage);
        }

        public override string GetDescription()
        {
            if((int)this.Operator < 2)
                return String.Format("Current user {0} {1}", this.Operator == CurrentUserOperator.BelongsTo ? " belongs to " : " does not belong to ", this.SecurityEntity.AllNames());
            else
                return String.Format("Current user {0}", this.Operator == CurrentUserOperator.IsSiteAdministrator ? " is site administrator" : " is not site administrator");
        }

        public override void SyncChanges(PageActionEditor editor, int index)
        {
            PeopleEditor pe = editor.FindControl("CUPeopleEditor" + index) as PeopleEditor;
            if (this.SecurityEntity != null)
                pe.CommaSeparatedAccounts = this.SecurityEntity.ToString(",");
            
            (editor.FindControl("CUOperator" + index) as DropDownList).SelectedValue = this.Operator.ToString();
        }

        public override void ApplyChanges(PageActionEditor editor, int index)
        {
            this.Operator = (CurrentUserOperator)Enum.Parse(typeof(CurrentUserOperator), (editor.FindControl("CUOperator" + index) as DropDownList).SelectedValue);

            SecurityEntity se = new SecurityEntity();
            if ((int)this.Operator < 2)
            {
                bool check = false;
                PeopleEditor pe = editor.FindControl("CUPeopleEditor" + index) as PeopleEditor;

                foreach (PickerEntity entity in pe.Entities)
                {
                    if (!entity.IsResolved)
                        continue;

                    string account = entity.Description;
                    string type = Convert.ToString(entity.EntityData["PrincipalType"]);
                    se.Add((PrincipalType)Enum.Parse(typeof(PrincipalType), type, true), account);
                    check = true;
                }
                if (!check)
                    editor.RaiseError("CUValue" + index, "Specify a list of user accounts, group accounts in Active Directory and/or SharePoint group names.");
            }

            this.SecurityEntity = se;            
        }

        public override bool Evaluate(Page page, PageActionWebPart part)
        {
            if (this.SecurityEntity == null)
                throw new ArgumentException("No SecurityEntity specified.");

            bool checkResult;
            if ((int)this.Operator < 2)
            {
                if(this.SecurityEntity.IsEmpty)
                    throw new InvalidOperationException("No user accounts, group accounts in Active Directory or SharePoint group names specified.");

                checkResult = this.SecurityEntity.CheckCurrentUser(SPContext.Current.Web);
                return checkResult && this.Operator == CurrentUserOperator.BelongsTo || !checkResult && this.Operator == CurrentUserOperator.DoesNotBelongTo;
            }
            else
            {
                checkResult = SPContext.Current.Web.CurrentUser.IsSiteAdmin;
                return checkResult && this.Operator == CurrentUserOperator.IsSiteAdministrator || !checkResult && this.Operator == CurrentUserOperator.IsNotSiteAdministrator;
            }
        }

        #endregion
    }

    #region CurrentUserOperator enum

    public enum CurrentUserOperator
    {
        BelongsTo = 0,
        DoesNotBelongTo = 1,
        IsSiteAdministrator = 2,
        IsNotSiteAdministrator = 3
    }

    #endregion
}
